<!DOCTYPE html>
<html>
<head>
  <title>Mosaic Example Gallery</title>
  <link href="./styles.css" rel="stylesheet">
</head>
<body>
  <header>
    <span>
      Spec:
      <select id="examples">
        <option value="none"></option>
        <option value="aeromagnetic-survey">Aeromagnetic Survey</option>
        <option value="airline-travelers">Airline Travelers</option>
        <option value="athletes">Athletes</option>
        <option value="athlete-birth-waffle">Athlete Birth Waffle</option>
        <option value="athlete-height">Athlete Height Intervals</option>
        <option value="axes">Axes &amp; Gridlines</option>
        <option value="bias">Bias Parameter</option>
        <option value="contours">Contours</option>
        <option value="crossfilter">Crossfilter</option>
        <option value="density-groups">Density Groups</option>
        <option value="density1d">Density 1D</option>
        <option value="density2d">Density 2D</option>
        <option value="driving-shifts">Driving Shifts into Reverse</option>
        <option value="earthquakes-feed">Earthquakes Feed</option>
        <option value="earthquakes-globe">Earthquakes Globe</option>
        <option value="facet-interval">Facet Interval</option>
        <option value="flights-200k">Flights 200k</option>
        <option value="flights-10m">Flights 10M</option>
        <option value="flights-density">Flights Density</option>
        <option value="flights-hexbin">Flights Hexbin</option>
        <option value="gaia">Gaia Star Catalog</option>
        <option value="line-density">Line Density</option>
        <option value="line">Line</option>
        <option value="line-multi-series">Line Multi-Series</option>
        <option value="linear-regression">Linear Regression</option>
        <option value="linear-regression-10m">Linear Regression 10M</option>
        <option value="legends">Legends</option>
        <option value="mark-types">Mark Types</option>
        <option value="moving-average">Moving Average</option>
        <option value="normalize">Normalize Stocks</option>
        <option value="nyc-taxi-rides">NYC Taxi Rides</option>
        <option value="observable-latency">Observable Latency</option>
        <option value="overview-detail">Overview + Detail</option>
        <option value="pan-zoom">Pan + Zoom</option>
        <option value="population-arrows">Population Arrows</option>
        <option value="presidential-opinion">Presidential Opinion</option>
        <option value="protein-design">Protein Design</option>
        <option value="region-tests">Region Tests</option>
        <option value="seattle-temp">Seattle Temperatures</option>
        <option value="sorted-bars">Sorted Bars</option>
        <option value="splom">Scatter Plot Matrix</option>
        <option value="symbols">Symbols</option>
        <option value="table">Table</option>
        <option value="unemployment">Unemployment</option>
        <option value="us-county-map">U.S. County Map</option>
        <option value="us-state-map">U.S. State Map</option>
        <option value="voronoi">Voronoi</option>
        <option value="walmart-openings">Walmart Openings</option>
        <option value="weather">Seattle Weather</option>
        <option value="wind-map">Wind Map</option>
        <option value="window-frame">Window Frame</option>
        <option value="wnba-shots">WNBA Shot Chart</option>
      </select>
    </span>

    <span>
      Connector:
      <select id="connectors">
        <option value="wasm" selected>WASM</option>
        <option value="socket">Socket</option>
        <option value="rest">REST</option>
        <option value="rest_https">REST (HTTPS)</option>
      </select>
    </span>

    <details>
      <summary>Advanced Options</summary>
      <div>
        <div>
          Spec Type:
          <select id="source">
            <option value="yaml" selected>YAML</option>
            <option value="esm">ESM</option>
          </select>
        </div>
        <div>
          Log Queries:
          <input id="query-log" type="checkbox" />
        </div>
        <div>
          Cache Queries:
          <input id="cache" type="checkbox" checked />
        </div>
        <div>
          Consolidate Queries:
          <input id="consolidate" type="checkbox" checked />
        </div>
        <div>
          Pre-aggregate:
          <input id="preagg" type="checkbox" checked />
        </div>
        <div>
          Pre-aggregate State:
          <button id="preagg-state">Log</button>
        </div>
      </div>
    </details>
  </header>
  <div id="view"></div>
<script type="module">
  import yaml from '../node_modules/yaml/browser/index.js';
  import { astToDOM, astToESM, clear, parseSpec, setDatabaseConnector, vg } from './setup.ts';

  const view = document.querySelector('#view');
  const connectorMenu = document.querySelector('#connectors');
  const exampleMenu = document.querySelector('#examples');
  const sourceMenu = document.querySelector('#source');
  const qlogToggle = document.querySelector('#query-log');
  const cacheToggle = document.querySelector('#cache');
  const consolidateToggle = document.querySelector('#consolidate');
  const preaggToggle = document.querySelector('#preagg');
  const preaggState = document.querySelector('#preagg-state');

  connectorMenu.addEventListener('change', setConnector);
  exampleMenu.addEventListener('change', reload);
  sourceMenu.addEventListener('change', reload);
  qlogToggle.addEventListener('input', setQueryLog);
  cacheToggle.addEventListener('input', setCache);
  consolidateToggle.addEventListener('input', setConsolidate);
  preaggToggle.addEventListener('input', setPreAggregate);
  preaggState.addEventListener('click', () => {
    const { entries } = vg.coordinator().preaggregator || {};
    if (entries) {
      console.warn(
        'Pre-aggregate Entries',
        Array.from(entries.values())
      );
    } else {
      console.warn('No Pre-aggregate Entries');
    }
  });

  setQueryLog();
  setCache();
  setConsolidate();
  setPreAggregate();
  setConnector();

  async function setConnector() {
    await setDatabaseConnector(connectorMenu.value);
    reload();
  }

  function setQueryLog() {
    vg.coordinator().manager.logQueries(qlogToggle.checked);
  }

  function setCache() {
    vg.coordinator().manager.cache(cacheToggle.checked);
  }

  function setConsolidate() {
    vg.coordinator().manager.consolidate(consolidateToggle.checked);
  }

  function setPreAggregate() {
    vg.coordinator().preaggregator.enabled = preaggToggle.checked;
  }

  function reload() {
    load(exampleMenu.value, sourceMenu.value);
  }

  async function load(name, source) {
    view.replaceChildren();

    let dir = '../specs/yaml';
    if (name === 'none' && location.search) {
      // get example name from query string
      name = location.search.slice(1);
      if (name.startsWith('dev:')) {
        // route to local spec for testing / exploration
        name = name.slice(4);
        dir = './specs';
      }
    }
    if (name !== 'none') {
      const spec = yaml.parse(
        await fetch(`${dir}/${name}.yaml`).then(res => res.text())
      );

      // options for output generation
      const baseURL = location.origin + '/';
      const options = connectorMenu.value === 'wasm' ? { baseURL } : {};

      // parse and load spec
      const ast = parseSpec(spec);
      const el = await (source === 'esm' ? loadESM : loadDOM)(ast, options);
      view.replaceChildren(el);
    }
  }

  async function loadDOM(ast, options) {
    clear();
    const { element } = await astToDOM(ast, { ...options, api: vg });
    return element;
  }

  async function loadESM(ast, options) {
    const vgplot = new URL('./setup.js', window.location.href).toString();
    const imports = new Map([[vgplot, ['vg', 'clear']]]);
    const preamble = 'clear();';
    const code = astToESM(ast, { ...options, imports, preamble });
    console.log(code);
    const blob = new Blob([code], { type: 'text/javascript' });
    const url = URL.createObjectURL(blob);
    return (await import(/* @vite-ignore */ url)).default;
  }
</script>
</body>
</html>
